package com.smarttest.common.util.protocol;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.smarttest.common.beans.protolcol.CTBox12Alarm;
import com.smarttest.common.beans.protolcol.Index;
import com.smarttest.common.beans.protolcol.LctTraceManager;
import com.smarttest.common.beans.protolcol.SmartMessage;
import com.smarttest.common.constants.SmartConstant;
import com.google.common.collect.Lists;

public class CmdColdChainAlarmParse {
	protected Logger logger = LoggerFactory.getLogger(this.getClass());
	
	/**附加信息在消息体的开始位置*/
    private static final int ADDTION_INFO_IDX = 29;   
    
    /**冷链报警期间的极限温度值和平均温度值，见表“报警极值平均值结构表”*/
    private static final byte ADDTION_ID = 0x01;
	
	public CTBox12Alarm parse(SmartMessage msg) {
		//解析消息体
		CTBox12Alarm ctbAlarm = getCTBoxAlarm(msg);
		return ctbAlarm;
	}
	
	//报警状态 	0 正常 1 低湿(低温)预警 2	低湿(低温)报警	3 高湿(高温)预警 4 高湿(高温)报警 5 传感器初始化中 6 传感器故障
	private final static Map<Integer,Integer> alarmMap = new HashMap<Integer,Integer>(30){/**  */
		private static final long serialVersionUID = 1L;

	{
		put(0,1);put(1,1);put(2,2);put(3,2);put(4,3);put(5,3);put(6,4);put(7,4);
		put(8,1);put(9,1);put(10,2);put(11,2);put(12,3);put(13,3);put(14,4);put(15,4);
		put(16,5);put(17,5);put(18,6);put(19,6);
	}};
	
	//报警类型   0温度报警  1湿度报警2:传感器初始化中 3:传感器故障
	private final static Map<Integer,Integer> typeMap = new HashMap<Integer,Integer>(30){/**  */
		private static final long serialVersionUID = 1L;

	{
		put(0,0);put(1,0);put(2,0);put(3,0);put(4,0);put(5,0);put(6,0);put(7,0);
		put(8,1);put(9,1);put(10,1);put(11,1);put(12,1);put(13,1);put(14,1);put(15,1);
		put(16,2);put(17,2);put(18,3);put(19,3);
	}};
	
	/**报警期间温度操作对应的温湿度报警值范围 3,7,11,15 */
    private static final List<Integer> ALARM_PERIOD_OPTIONS= Lists.newArrayList(3, 7, 11, 15);
	
	private CTBox12Alarm getCTBoxAlarm(SmartMessage msg){
		byte[] data = msg.getData();
		if(data == null || data.length <= 0)
			return null;
		int gtp;	//设备自身温度:1摄氏度；MSB为符号位
		int speed;	//速度
		int acc;	//ACC状态 0:关；1：开；2：无法获取状态
		int compressor;	//压缩机状态0:关；1：开；2：无法获取状态
		int door;	//门开关状态0:关；1：开；2：无法获取状态
		int num;	//通道号
		int alarmType; //温度：0~7；湿度：8~15 传感器:16~19
		float alarmset = 0;	//报警设置值
		float alarmt;	//温度值
		float alarmm;	//湿度值
		Index index = new Index();
		//信息长度
		index.add(1);
		
		CTBox12Alarm ctbAlarm = new CTBox12Alarm();
		ctbAlarm.setImei(msg.getImei());
		//采集时间
		Date time = ByteUtil.bcd2Date(data, index);
		ctbAlarm.setTime(time);
		//设备自身温度
		gtp = ByteUtil.parseByte2IntSign(data, index);
		ctbAlarm.setGtp(gtp);
		
		//经纬度			location 
		double lng = (double)(ByteUtil.parseDWord(data, index))/1000000.0;
		double lat = (double)(ByteUtil.parseDWord(data, index))/1000000.0;
		ctbAlarm.setLng(lng);
		ctbAlarm.setLat(lat);
		//速度
		
		speed = ByteUtil.parseWord(data, index);
		ctbAlarm.setSpeed(speed);
		acc = ByteUtil.parseByte2Int(data, index);
		ctbAlarm.setAcc(acc);
		compressor = ByteUtil.parseByte2Int(data, index);
		ctbAlarm.setCompressor(compressor);
		door = ByteUtil.parseByte2Int(data, index);
		ctbAlarm.setDoor(door);
		
		//通道号
		num = ByteUtil.parseByte2Int(data, index);
		ctbAlarm.setNum(num);
		//温湿度报警值 温度：0~7；湿度：8~15
		alarmType = ByteUtil.parseByte2Int(data, index);
		//报警类型   0温度报警  1湿度报警2:传感器初始化中 3:传感器故障
		ctbAlarm.setType(typeMap.get(alarmType));
		//报警状态 	0 正常 1 低湿(低温)预警 2	低湿(低温)报警	3 高湿(高温)预警 4 高湿(高温)报警 5 传感器初始化中 6 传感器故障
		ctbAlarm.setAlarm(alarmMap.get(alarmType));
		
		//1结束	0 开始
		ctbAlarm.setEnd(alarmType%2);
		//0:温度报警	1：湿度报警		2:传感器初始化中 		3:传感器故障
		if(alarmType >= 0 && alarmType <= 7){
			//报警设置值
			alarmset = new Float(ByteUtil.parseWordSign(data, index))/10;
		}else if(alarmType >= 8 && alarmType <= 15){
			//报警设置值
			alarmset = new Float(ByteUtil.parseWord(data, index))/10;
		}else if(alarmType >= 16 && alarmType <= 19){
		}
		ctbAlarm.setAlarmset(alarmset);
		
		
		//温度值
		alarmt = parseSensorWord(data, index, SmartConstant.COLDCHAIN_ALARM_TYPE.ALARMT);
		//湿度值
		alarmm = parseSensorWord(data, index, SmartConstant.COLDCHAIN_ALARM_TYPE.ALARMM);
		ctbAlarm.setAlarmt(alarmt);
		ctbAlarm.setAlarmm(alarmm);
		
		//处理附加信息
        processAdditionInfo(data, alarmType, ctbAlarm);
        
		return ctbAlarm;
	}
	
	/**
     * 处理附加信息
     * 
     * @param data
     * @param alarmType
     * @param ctbAlarm
     */
    private void processAdditionInfo(byte[] data, int alarmType, CTBox12Alarm ctbAlarm) {
        if (data.length < ADDTION_INFO_IDX + 1) {
            return;
        }
        try {
            //获取附加信息
            Map<Byte, Object> additionInfo = parseAdditionInfo(data, ADDTION_INFO_IDX);
            
            //判断附加信息是否为冷链报警期间的极限温度值和平均温度值
            boolean avgAlarmAddition = additionInfo.containsKey(ADDTION_ID) && ALARM_PERIOD_OPTIONS.contains(alarmType);
            if(!avgAlarmAddition){
                return;
            }
                
            //报警期间温度极限值
            Index index = new Index();
            byte[] addition = (byte[]) additionInfo.get(ADDTION_ID);
            ctbAlarm.setAlarmLimitTemperature(new Float(ByteUtil.parseWordSign(addition, index)) / 10);
            
            //报警期间平均温度
            ctbAlarm.setAlarmAverageTemperature(new Float(ByteUtil.parseWordSign(addition, index)) / 10); 
            
        } catch (Exception e) {
            logger.error("0x13指令处理报警期间温度极限值附加信息异常, data:{}", Hex.encodeHexString(data), e);
        }
    }
    
    /**
     * 解析附加信息
     * 
     * @param data
     * @param index
     * @return
     */
    private static Map<Byte, Object> parseAdditionInfo(byte[] data, int index) {
        Map<Byte, Object> additionInfo = new HashMap<Byte, Object>();
        int cnt = 0;
        while (index+1 < data.length && cnt<100) { //id, length两个字节必须，防止死循环
            byte id = data[index++];
            int length = (data[index++]) & 0xff;
            //防止错误报文导致长度越界
            if (length==0 || index + length > data.length) break;
            
            byte[] result = new byte[length];
            System.arraycopy(data, index, result, 0, length);
            additionInfo.put(id, result);
            index = index + length;
            cnt++;
        }
        return additionInfo;
    }
	
	/**
	 * 传感器Word转换为int
	 * 
	 * @param in       入参Data
	 * @param index    索引
	 * @param type     报警类型
	 * @return
	 */
    @SuppressWarnings("null")
    private float parseSensorWord(byte[] in,Index index,String type){
        byte[] data = new byte[]{in[index.add()],in[index.add()]};
        int value = ((data[0]& 0xff) << 8) + (data[1] & 0xff);
        
        Integer result = SmartConstant.SENSOR_STATUS.get(value) ;
        if(null == result ){
            if(StringUtils.equals(SmartConstant.COLDCHAIN_ALARM_TYPE.ALARMT, type)){//温度
                return new Float(ByteUtil.parseWordSign(data, new Index()))/10;
            }
            
            if(StringUtils.equals(SmartConstant.COLDCHAIN_ALARM_TYPE.ALARMM, type)){//湿度
               return new Float(ByteUtil.parseWord(data, new Index()))/10;
            }
        }
        return result;
    }
}
